// File: jmcomic-core/src/main/java/dev/jukomu/jmcomic/entity/IndexedEntity.java
package dev.jukomu.jmcomic.entity;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * 对应Python的IndexedEntity，表示一个可按索引访问的实体集合。
 *
 * @param <T> 集合中元素的类型
 */
public interface IndexedEntity<T> extends Iterable<T> {

    /**
     * 获取指定索引的元素。
     * 对应Python的getindex方法。
     *
     * @param index 索引
     * @return 元素
     */
    T get(int index);

    /**
     * 获取集合中元素的数量。
     * 对应Python的__len__方法。
     *
     * @return 元素数量
     */
    int size();

    /**
     * 模拟Python的切片操作（getitem）。
     *
     * @param startIndex 起始索引（包含）
     * @param endIndex   结束索引（不包含）
     * @param step       步长
     * @return 元素的List
     */
    default List<T> getSlice(int startIndex, int endIndex, int step) {
        int actualStartIndex = startIndex < 0 ? Math.max(0, size() + startIndex) : startIndex;
        int actualEndIndex = endIndex < 0 ? Math.max(0, size() + endIndex) : (endIndex > size() ? size() : endIndex);
        if (actualEndIndex < actualStartIndex) { // Handle empty slice case
            return new ArrayList<>();
        }
        if (step <= 0) {
            throw new IllegalArgumentException("Step must be positive.");
        }

        List<T> result = new ArrayList<>();
        for (int i = actualStartIndex; i < actualEndIndex; i += step) {
            result.add(get(i));
        }
        return result;
    }

    /**
     * 模拟Python的切片操作，使用默认步长1。
     *
     * @param startIndex 起始索引
     * @param endIndex   结束索引
     * @return 元素的List
     */
    default List<T> getSlice(int startIndex, int endIndex) {
        return getSlice(startIndex, endIndex, 1);
    }

    /**
     * 获取所有元素的List。
     *
     * @return 元素的List
     */
    default List<T> toList() {
        return getSlice(0, size(), 1);
    }

    /**
     * 返回迭代器。
     * 对应Python的__iter__方法。
     *
     * @return 迭代器
     */
    @Override
    default Iterator<T> iterator() {
        return new Iterator<T>() {
            private int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return currentIndex < size();
            }

            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                return get(currentIndex++);
            }
        };
    }
}